Public NotInheritable Class CompositeViewerForm

    Public CompositeMatrix As MatrixDataStructures.Matrix3DInt16
    Dim fMRIThreshold, FAThreshold, PerfusionThreshold As Single
    Dim fMRIColor, FAColor, PerfusionColor As Color
    Dim ColorToAbsScaleF, ColorToAbsScaleD, ColorToAbsScaleP _
    , ColorScaleFMax, ColorScaleDMax, ColorScalePMax _
    , ColorScaleFMin, ColorScaleDMin, ColorScalePMin As Single
    Dim CompositeDisplay As New MainForm

    Private Sub CompositeViewerForm_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.GotFocus
        CompositeDisplay.Focus()
        CompositeDisplay.BringToFront()
        If CompositeDisplay.Visible = False Then CompositeDisplay.Visible = True
        CompositeDisplay.TopMost = True
        CompositeDisplay.Size = PictureBox4.Size
        Dim temp As Point = Me.PointToScreen(PictureBox4.Location)
        temp.Y += Me.SplitContainer1.Panel1.Height + 5
        CompositeDisplay.Location = temp
        '    AddHandler CompositeDisplay.LostFocus, AddressOf CloseCompositeDisplay
        AddHandler CompositeDisplay.CurrentSlice, AddressOf CurrentSliceInformation
    End Sub

    Private Sub SplashScreen1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim temp As New Bitmap(PictureBox1.Width, PictureBox1.Height)
        For i As Integer = 0 To temp.Width - 1
            For j As Integer = 0 To temp.Height - 1
                temp.SetPixel(i, j, Color.Red)
            Next
        Next

        PictureBox1.Image = temp
        PictureBox2.Image = temp
        PictureBox3.Image = temp

        ColorToAbsScaleF = 1
        ColorToAbsScaleD = 1
        ColorToAbsScaleP = 1

        ColorScaleFMin = 0
        ColorScaleDMin = 0
        ColorScalePMin = 0

        If My.Forms.FormMain.AnatomyDisplay IsNot Nothing And FormMain.AnatomyVolume IsNot Nothing Then
            CheckBoxA.Enabled = True
        End If
        If FormMain.fMRIDisplay IsNot Nothing And FormMain.fMRIVolume IsNot Nothing Then
            CheckBoxF.Enabled = True
            ColorToAbsScaleF = CSng((FormMain.fMRIVolume.Matrix.Maximum - FormMain.fMRIVolume.Matrix.Minimum) / 255)
            ColorScaleFMin = FormMain.fMRIVolume.Matrix.Minimum
            ColorScaleFMax = FormMain.fMRIVolume.Matrix.Maximum
        End If
        If FormMain.DiffusionDisplay IsNot Nothing And FormMain.FAVolume IsNot Nothing Then
            CheckBoxD.Enabled = True
            ColorToAbsScaleD = CSng((FormMain.FAVolume.MatrixD.Maximum - FormMain.FAVolume.MatrixD.Minimum) / 255)
            ColorScaleDMin = FormMain.FAVolume.MatrixD.Minimum
            ColorScaleDMax = FormMain.FAVolume.MatrixD.Maximum
        End If
        If FormMain.PerfusionDisplay IsNot Nothing And FormMain.PerfusionVolume IsNot Nothing Then
            CheckBoxP.Enabled = True
            ColorToAbsScaleP = CSng((FormMain.PerfusionVolume.MatrixD.Maximum - FormMain.PerfusionVolume.MatrixD.Minimum) / 255)
            ColorScalePMin = FormMain.PerfusionVolume.MatrixD.Minimum
            ColorScalePMax = FormMain.PerfusionVolume.MatrixD.Maximum
        End If

        fMRIColor = Color.Red
        FAColor = Color.Red
        PerfusionColor = Color.Red

        Label2.Text = CStr(ColorSlider2.Min * ColorToAbsScaleF + ColorScaleFMin)
        Label3.Text = CStr(ColorSlider3.Min * ColorToAbsScaleD + ColorScaleDMin)
        Label4.Text = CStr(ColorSlider4.Min * ColorToAbsScaleP + ColorScalePMin)

    End Sub

    Public Sub ComposeData()

        Dim SpectralColorMapObject As New SPMSpectralColorMap

        'Anatomy Always has to be loaded
        'Compare everything else to anatomy first
        If CheckBoxA.Checked = False Or CheckBoxA.Enabled = False Then
            MsgBox("AnatomyData is necessary to create Composite Maps!", MsgBoxStyle.Exclamation)
            Exit Sub
        End If
        'Otherwise
        If FormMain.fMRIVolume IsNot Nothing And CheckBoxF.Enabled = True And CheckBoxF.Checked = True Then
            If FormMain.fMRIVolume.Matrix.x <> FormMain.AnatomyVolume.Matrix.x _
            Or FormMain.fMRIVolume.Matrix.y <> FormMain.AnatomyVolume.Matrix.y _
            Or FormMain.fMRIVolume.Matrix.z <> FormMain.AnatomyVolume.Matrix.z Then
                MsgBox("fMRI/Anatomy Matrix size mismatch!", MsgBoxStyle.Exclamation)
                Exit Sub
            End If
        End If
        If FormMain.FAVolume IsNot Nothing And FormMain.IsFACalculated = True And CheckBoxD.Checked = True Then
            If FormMain.FAVolume.MatrixD.x <> FormMain.AnatomyVolume.Matrix.x _
            Or FormMain.FAVolume.MatrixD.y <> FormMain.AnatomyVolume.Matrix.y _
            Or FormMain.FAVolume.MatrixD.z <> FormMain.AnatomyVolume.Matrix.z Then
                MsgBox("FA/Anatomy Matrix size mismatch!", MsgBoxStyle.Exclamation)
                Exit Sub
            End If
        ElseIf CheckBoxD.Checked = True And FormMain.IsFACalculated = False Then
            MsgBox("FA Needs to be calculated before creating Composite Maps!")
            Exit Sub
        End If
        If FormMain.PerfusionDisplay IsNot Nothing And CheckBoxP.Checked = True Then
            If FormMain.PerfusionVolume.MatrixD.x <> FormMain.AnatomyVolume.Matrix.x _
            Or FormMain.PerfusionVolume.MatrixD.y <> FormMain.AnatomyVolume.Matrix.y _
            Or FormMain.PerfusionVolume.MatrixD.z <> FormMain.AnatomyVolume.Matrix.z Then
                MsgBox("Perfusion/Anatomy Matrix size mismatch!", MsgBoxStyle.Exclamation)
                Exit Sub
            End If
        End If
        'Continue if all sizes match and atleast one is loaded

        fMRIThreshold = CSng(Label2.Text)
        FAThreshold = CSng(Label3.Text)
        PerfusionThreshold = CSng(Label4.Text)

        'Load AnatomyData into CompositeMatrix first
        CompositeMatrix = FormMain.AnatomyVolume.Matrix

        'Scale CompositeMatrix from 0 - 225
        CompositeMatrix = CompositeMatrix.ReScale(CompositeMatrix, 0, 255)

        'Create a ColorMatrix
        Dim ColorMatrix As New MatrixDataStructures.ColorMatrix(CompositeMatrix.x, CompositeMatrix.y, CompositeMatrix.z)
        For i As Integer = 0 To CompositeMatrix.x - 1
            For j As Integer = 0 To CompositeMatrix.y - 1
                For k As Integer = 0 To CompositeMatrix.z - 1
                    ColorMatrix.data(i, j, k) = Color.FromArgb(CInt(CompositeMatrix.data(i, j, k)), CInt(CompositeMatrix.data(i, j, k)), CInt(CompositeMatrix.data(i, j, k)))
                Next
            Next
        Next

        CompositeMatrix.Dispose()

        'Order of Importance: fMRI, FA, Perfusion

        Dim tempcolor As New Color

        'if fMRI is loaded and checked
        If FormMain.fMRIVolume IsNot Nothing And CheckBoxF.Checked = True Then
            For i As Integer = 0 To ColorMatrix.x - 1
                For j As Integer = 0 To ColorMatrix.y - 1
                    For k As Integer = 0 To ColorMatrix.z - 1
                        If FormMain.fMRIVolume.Matrix.data(i, j, k) >= fMRIThreshold Then
                            If CheckedListBox1.GetItemCheckState(0) = CheckState.Checked Then
                                tempcolor = Color.FromArgb(CInt(((FormMain.fMRIVolume.Matrix.data(i, j, k) - fMRIThreshold) / (ColorScaleFMax - fMRIThreshold)) * fMRIColor.R), fMRIColor.R, fMRIColor.G, fMRIColor.B)
                                ColorMatrix.data(i, j, k) = tempcolor
                            ElseIf CheckedListBox1.GetItemCheckState(1) = CheckState.Checked Then
                                tempcolor = Color.FromArgb(CInt(((FormMain.fMRIVolume.Matrix.data(i, j, k) - fMRIThreshold) / (ColorScaleFMax - fMRIThreshold)) * fMRIColor.R) _
                                , CInt(((FormMain.fMRIVolume.Matrix.data(i, j, k) - fMRIThreshold) / (ColorScaleFMax - fMRIThreshold)) * fMRIColor.G) _
                                , CInt(((FormMain.fMRIVolume.Matrix.data(i, j, k) - fMRIThreshold) / (ColorScaleFMax - fMRIThreshold)) * fMRIColor.B))
                                ColorMatrix.data(i, j, k) = tempcolor
                            Else
                                ColorMatrix.data(i, j, k) = SpectralColorMapObject.ReturnValue(FormMain.fMRIVolume.Matrix.data(i, j, k), ColorScaleFMax, fMRIThreshold)
                            End If
                        End If
                    Next
                Next
            Next
        End If

        'if FA is loaded and checked
        If FormMain.FAVolume IsNot Nothing And CheckBoxD.Checked = True Then
            For i As Integer = 0 To ColorMatrix.x - 1
                For j As Integer = 0 To ColorMatrix.y - 1
                    For k As Integer = 0 To ColorMatrix.z - 1
                        If FormMain.FAVolume.MatrixD.data(i, j, k) >= FAThreshold Then
                            If CheckedListBox2.GetItemCheckState(0) = CheckState.Checked Then
                                tempcolor = Color.FromArgb(CInt(((FormMain.FAVolume.MatrixD.data(i, j, k) - FAThreshold) / (ColorScaleDMax - FAThreshold)) * 255), FAColor.R, FAColor.G, FAColor.B)
                                ColorMatrix.data(i, j, k) = tempcolor
                            ElseIf CheckedListBox2.GetItemCheckState(1) = CheckState.Checked Then
                                tempcolor = Color.FromArgb(CInt(((FormMain.FAVolume.MatrixD.data(i, j, k) - FAThreshold) / (ColorScaleDMax - FAThreshold)) * FAColor.R) _
                          , CInt(((FormMain.FAVolume.MatrixD.data(i, j, k) - FAThreshold) / (ColorScaleDMax - FAThreshold)) * FAColor.G) _
                          , CInt(((FormMain.FAVolume.MatrixD.data(i, j, k) - FAThreshold) / (ColorScaleDMax - FAThreshold)) * FAColor.B))
                                ColorMatrix.data(i, j, k) = tempcolor
                            Else
                                ColorMatrix.data(i, j, k) = SpectralColorMapObject.ReturnValue(FormMain.FAVolume.MatrixD.data(i, j, k), ColorScaleDMax, FAThreshold)
                            End If
                        End If
                    Next
                Next
            Next
        End If

        'if Perfusion is loaded and checked
        If FormMain.PerfusionVolume IsNot Nothing And CheckBoxP.Enabled = True Then
            For i As Integer = 0 To ColorMatrix.x - 1
                For j As Integer = 0 To ColorMatrix.y - 1
                    For k As Integer = 0 To ColorMatrix.z - 1
                        If FormMain.PerfusionVolume.MatrixD.data(i, j, k) >= PerfusionThreshold Then
                            If CheckedListBox2.GetItemCheckState(0) = CheckState.Checked Then
                                tempcolor = Color.FromArgb(CInt(((FormMain.PerfusionVolume.MatrixD.data(i, j, k) - PerfusionThreshold) / (ColorScalePMax - PerfusionThreshold)) * PerfusionColor.R), PerfusionColor.R, PerfusionColor.G, PerfusionColor.B)
                                ColorMatrix.data(i, j, k) = tempcolor
                            ElseIf CheckedListBox2.GetItemCheckState(0) = CheckState.Checked Then
                                tempcolor = Color.FromArgb(CInt(((FormMain.PerfusionVolume.MatrixD.data(i, j, k) - PerfusionThreshold) / (ColorScalePMax - PerfusionThreshold)) * PerfusionColor.R) _
                        , CInt(((FormMain.PerfusionVolume.MatrixD.data(i, j, k) - PerfusionThreshold) / (ColorScalePMax - PerfusionThreshold)) * PerfusionColor.G) _
                        , CInt(((FormMain.PerfusionVolume.MatrixD.data(i, j, k) - PerfusionThreshold) / (ColorScalePMax - PerfusionThreshold)) * PerfusionColor.B))
                                ColorMatrix.data(i, j, k) = tempcolor
                            Else
                                ColorMatrix.data(i, j, k) = SpectralColorMapObject.ReturnValue(FormMain.PerfusionVolume.MatrixD.data(i, j, k), ColorScalePMax, PerfusionThreshold)
                            End If
                        End If
                    Next
                Next
            Next
        End If

        CompositeDisplay.Show()
        ' CompositeDisplay.MdiParent = Me
        If CompositeDisplay.Visible = False Then CompositeDisplay.Visible = True
        'CompositeDisplay.OpenFile(ColorMatrix)
        CompositeDisplay.TopMost = True
        CompositeDisplay.Size = PictureBox4.Size
        Dim temp As Point = Me.PointToScreen(PictureBox4.Location)
        temp.Y += Me.SplitContainer1.Panel1.Height + 5
        CompositeDisplay.Location = temp
        '    AddHandler CompositeDisplay.LostFocus, AddressOf CloseCompositeDisplay
        AddHandler CompositeDisplay.CurrentSlice, AddressOf CurrentSliceInformation
        CompositeDisplay.ChangeCurrentSliceInfo(Mid(GetFirstBit(Me.CurrentActiveDisplay), 1, 1), CurrentActiveSlice)
    End Sub

    Public Function GetFirstBit(ByVal Val As MainForm.DisplayType) As String
        Select Case Val
            Case MainForm.DisplayType.Coronal
                Return "c"
            Case MainForm.DisplayType.Sagittal
                Return "s"
            Case MainForm.DisplayType.Transverse
                Return "t"
            Case Else
                Return "t"
        End Select
    End Function

    Public CurrentActiveDisplay As MainForm.DisplayType = MainForm.DisplayType.Coronal
    Public CurrentActiveSlice As Integer
    Public Sub CurrentSliceInformation(ByVal sender As Object, ByVal e As EventArgs)
        Dim sliceinfo As String = CType(sender, String)
        Select Case Mid(sliceinfo, 1, 1)
            Case "t"
                CurrentActiveDisplay = MainForm.DisplayType.Transverse
            Case "c"
                CurrentActiveDisplay = MainForm.DisplayType.Coronal
            Case "s"
                CurrentActiveDisplay = MainForm.DisplayType.Sagittal
        End Select
        CurrentActiveSlice = CInt(Mid(sliceinfo, 2, sliceinfo.Length - 1))
    End Sub
    Private Sub ClosdeCompositeDisplay(ByVal sender As Object, ByVal e As EventArgs)
        If CompositeDisplay IsNot Nothing Then
            CompositeDisplay.Visible = True
        End If
    End Sub

    Dim WithEvents Composite As MainForm

    Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
        Me.ComposeData()
    End Sub

    Public Sub New()

        ' This call is required by the Windows Form Designer.
        InitializeComponent()

    End Sub

    Private Sub ColorSlider2_ValuesChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ColorSlider2.ValuesChanged
        Label2.Text = CStr(ColorSlider2.Min * ColorToAbsScaleF + ColorScaleFMin)
    End Sub

    Private Sub ColorSlider3_ValuesChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ColorSlider3.ValuesChanged
        Label3.Text = CStr(ColorSlider3.Min * ColorToAbsScaleD + ColorScaleDMin)
    End Sub

    Private Sub ColorSlider4_ValuesChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ColorSlider4.ValuesChanged
        Label4.Text = CStr(ColorSlider4.Min * ColorToAbsScaleP + ColorScalePMin)
    End Sub

    Private Sub Button5_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
        If CompositeDisplay IsNot Nothing Then CompositeDisplay.Close()
        Me.Close()
    End Sub

    Private Sub PictureBox3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox3.Click
        If ColorDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
            Dim temp As New Bitmap(PictureBox1.Width, PictureBox1.Height)
            For i As Integer = 0 To temp.Width - 1
                For j As Integer = 0 To temp.Height - 1
                    temp.SetPixel(i, j, ColorDialog1.Color)
                Next
            Next
            PictureBox3.Image = temp
            fMRIColor = ColorDialog1.Color
        End If
    End Sub

    Private Sub PictureBox2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox2.Click
        If ColorDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
            Dim temp As New Bitmap(PictureBox1.Width, PictureBox1.Height)
            For i As Integer = 0 To temp.Width - 1
                For j As Integer = 0 To temp.Height - 1
                    temp.SetPixel(i, j, ColorDialog1.Color)
                Next
            Next
            PictureBox2.Image = temp
            FAColor = ColorDialog1.Color
        End If
    End Sub

    Private Sub PictureBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox1.Click
        If ColorDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
            Dim temp As New Bitmap(PictureBox1.Width, PictureBox1.Height)
            For i As Integer = 0 To temp.Width - 1
                For j As Integer = 0 To temp.Height - 1
                    temp.SetPixel(i, j, ColorDialog1.Color)
                Next
            Next
            PictureBox1.Image = temp
            PerfusionColor = ColorDialog1.Color
        End If
    End Sub

    Private Sub CheckedListBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckedListBox1.SelectedIndexChanged
        If CheckedListBox1.GetItemCheckState(0) = CheckState.Checked Then
            CheckedListBox1.SetItemCheckState(1, CheckState.Unchecked)
        ElseIf CheckedListBox1.GetItemCheckState(0) = CheckState.Checked Then
            CheckedListBox1.SetItemCheckState(0, CheckState.Unchecked)
        End If
    End Sub

    Private Sub CheckedListBox2_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckedListBox2.SelectedIndexChanged
        If CheckedListBox2.GetItemCheckState(0) = CheckState.Checked Then
            CheckedListBox2.SetItemCheckState(1, CheckState.Unchecked)
        ElseIf CheckedListBox2.GetItemCheckState(0) = CheckState.Checked Then
            CheckedListBox2.SetItemCheckState(0, CheckState.Unchecked)
        End If
    End Sub

    Private Sub CheckedListBox3_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckedListBox3.SelectedIndexChanged
        If CheckedListBox3.GetItemCheckState(0) = CheckState.Checked Then
            CheckedListBox3.SetItemCheckState(1, CheckState.Unchecked)
        ElseIf CheckedListBox3.GetItemCheckState(0) = CheckState.Checked Then
            CheckedListBox3.SetItemCheckState(0, CheckState.Unchecked)
        End If
    End Sub

    Private Sub PictureBox4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox4.Click

    End Sub

    Private Sub CompositeViewerForm_Move(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Move
        CompositeDisplay.Focus()
        If CompositeDisplay.Visible = False Then CompositeDisplay.Visible = True
        CompositeDisplay.TopMost = True
        CompositeDisplay.Size = PictureBox4.Size
        Dim temp As Point = Me.PointToScreen(PictureBox4.Location)
        temp.Y += Me.SplitContainer1.Panel1.Height + 5
        CompositeDisplay.Location = temp
        '    AddHandler CompositeDisplay.LostFocus, AddressOf CloseCompositeDisplay
        AddHandler CompositeDisplay.CurrentSlice, AddressOf CurrentSliceInformation
    End Sub

    Private Sub CompositeViewerForm_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
        ' CompositeDisplay.MdiParent = Me
        CompositeDisplay.Focus()
        CompositeDisplay.BringToFront()
        If CompositeDisplay.Visible = False Then CompositeDisplay.Visible = True
        CompositeDisplay.TopMost = True
        CompositeDisplay.Size = PictureBox4.Size
        Dim temp As Point = Me.PointToScreen(PictureBox4.Location)
        temp.Y += Me.SplitContainer1.Panel1.Height + 5
        CompositeDisplay.Location = temp
        '    AddHandler CompositeDisplay.LostFocus, AddressOf CloseCompositeDisplay
        AddHandler CompositeDisplay.CurrentSlice, AddressOf CurrentSliceInformation
    End Sub

    Private Sub CompositeViewerForm_ResizeEnd(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ResizeEnd
        ' CompositeDisplay.MdiParent = Me
        CompositeDisplay.Focus()
        CompositeDisplay.BringToFront()
        If CompositeDisplay.Visible = False Then CompositeDisplay.Visible = True
        CompositeDisplay.TopMost = True
        CompositeDisplay.Size = PictureBox4.Size
        Dim temp As Point = Me.PointToScreen(PictureBox4.Location)
        temp.Y += Me.SplitContainer1.Panel1.Height + 5
        CompositeDisplay.Location = temp
        '    AddHandler CompositeDisplay.LostFocus, AddressOf CloseCompositeDisplay
        AddHandler CompositeDisplay.CurrentSlice, AddressOf CurrentSliceInformation
    End Sub

    Private Sub CompositeViewerForm_SizeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.SizeChanged
        ' CompositeDisplay.MdiParent = Me
        CompositeDisplay.Focus()
        CompositeDisplay.BringToFront()
        If CompositeDisplay.Visible = False Then CompositeDisplay.Visible = True
        CompositeDisplay.TopMost = True
        CompositeDisplay.Size = PictureBox4.Size
        Dim temp As Point = Me.PointToScreen(PictureBox4.Location)
        temp.Y += Me.SplitContainer1.Panel1.Height + 5
        CompositeDisplay.Location = temp
        '    AddHandler CompositeDisplay.LostFocus, AddressOf CloseCompositeDisplay
        AddHandler CompositeDisplay.CurrentSlice, AddressOf CurrentSliceInformation
    End Sub

    Private Sub CompositeViewerForm_Validated(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Validated
        ' CompositeDisplay.MdiParent = Me
        CompositeDisplay.Focus()
        CompositeDisplay.BringToFront()
        If CompositeDisplay.Visible = False Then CompositeDisplay.Visible = True
        CompositeDisplay.TopMost = True
        CompositeDisplay.Size = PictureBox4.Size
        Dim temp As Point = Me.PointToScreen(PictureBox4.Location)
        temp.Y += Me.SplitContainer1.Panel1.Height + 5
        CompositeDisplay.Location = temp
        '    AddHandler CompositeDisplay.LostFocus, AddressOf CloseCompositeDisplay
        AddHandler CompositeDisplay.CurrentSlice, AddressOf CurrentSliceInformation
    End Sub
End Class

Public Class SPMSpectralColorMap
    'Use the same spectral map as SPM
    'SPECTRAL Black-purple-blue-green-yellow-red-white color map.
    Private Base(,) As Single
    Private ColorMatrix As MatrixDataStructures.ColorMatrix
    Private ValuesMatrix As MatrixDataStructures.Matrix3DSingle
    Public Sub New()
        ReDim Base(21, 3)
        Base(0, 0) = 0.4667 : Base(0, 1) = 0.0 : Base(0, 2) = 0.5333
        Base(1, 0) = 0.5333 : Base(1, 1) = 0.0 : Base(1, 2) = 0.6
        Base(2, 0) = 0.0 : Base(2, 1) = 0.0 : Base(2, 2) = 0.6667
        Base(3, 0) = 0.0 : Base(3, 1) = 0.0 : Base(3, 2) = 0.8667
        Base(4, 0) = 0.0 : Base(4, 1) = 0.4667 : Base(4, 2) = 0.8667
        Base(5, 0) = 0.0 : Base(5, 1) = 0.6 : Base(5, 2) = 0.8667
        Base(6, 0) = 0.0 : Base(6, 1) = 0.6667 : Base(6, 2) = 0.6667
        Base(7, 0) = 0.0 : Base(7, 1) = 0.6667 : Base(7, 2) = 0.5333
        Base(8, 0) = 0.0 : Base(8, 1) = 0.6 : Base(8, 2) = 0.0
        Base(9, 0) = 0.0 : Base(9, 1) = 0.7333 : Base(9, 2) = 0.0
        Base(10, 0) = 0.0 : Base(10, 1) = 0.8667 : Base(10, 2) = 0.0
        Base(11, 0) = 0.0 : Base(11, 1) = 1.0 : Base(11, 2) = 0.0
        Base(12, 0) = 0.7333 : Base(12, 1) = 1.0 : Base(12, 2) = 0.0
        Base(13, 0) = 0.9333 : Base(13, 1) = 0.9333 : Base(13, 2) = 0.0
        Base(14, 0) = 1.0 : Base(14, 1) = 0.8 : Base(14, 2) = 0.0
        Base(15, 0) = 1.0 : Base(15, 1) = 0.6 : Base(15, 2) = 0.0
        Base(16, 0) = 1.0 : Base(16, 1) = 0.0 : Base(16, 2) = 0.0
        Base(17, 0) = 0.8667 : Base(17, 1) = 0.0 : Base(17, 2) = 0.0
        Base(18, 0) = 0.8 : Base(18, 1) = 0.0 : Base(18, 2) = 0.0
        Base(19, 0) = 0.8 : Base(19, 1) = 0.8 : Base(19, 2) = 0.8
        Base(20, 0) = 1.0 : Base(20, 1) = 1.0 : Base(20, 2) = 1.0
    End Sub
    
    Public Function ReturnValue(ByVal Value As Single, ByVal Max As Single, ByVal Min As Single) As Color
        Dim Temp As Single = 0
        Dim IndexH, IndexL As Integer
        Dim InterpolatedValue(3) As Double
        Temp = (Value - Min) / (Max - Min) 'scales from 0-1
        Temp = Temp * 20  'scales from 0-21
        IndexH = CInt(IIf(Math.Ceiling(Temp) >= 1, Math.Ceiling(Temp), 1))
        IndexL = IndexH - 1
        Temp = Temp - IndexL 'the decimal part
        ' InterpolatedValue(0) = Base(IndexH, 0)
        ' InterpolatedValue(1) = Base(IndexH, 1)
        ' InterpolatedValue(2) = Base(IndexH, 2)

        InterpolatedValue(0) = 0.5 * (Temp * Base(IndexL, 0) + (1 - Temp) * Base(IndexH, 0)) * 255
        InterpolatedValue(1) = 0.5 * (Temp * Base(IndexL, 1) + (1 - Temp) * Base(IndexH, 1)) * 255
        InterpolatedValue(2) = 0.5 * (Temp * Base(IndexL, 2) + (1 - Temp) * Base(IndexH, 2)) * 255
        Return Color.FromArgb(CInt(InterpolatedValue(0)), CInt(InterpolatedValue(1)), CInt(InterpolatedValue(2)))
    End Function
    Private Sub ComputeColorMatrix()
        ColorMatrix = New MatrixDataStructures.ColorMatrix(ValuesMatrix.x, ValuesMatrix.y, ValuesMatrix.z)
        Dim Min As Single = ValuesMatrix.Minimum
        Dim Max As Single = ValuesMatrix.Maximum
        Dim Temp As Single = 0
        Dim IndexH, IndexL As Integer
        Dim InterpolatedValue(3) As Double
        For i As Integer = 0 To ColorMatrix.x - 1
            For j As Integer = 0 To ColorMatrix.y - 1
                For k As Integer = 0 To ColorMatrix.z - 1
                    ' now scale the value from 1-21
                    ' choose matrix index based on +-1 integer
                    Temp = (ValuesMatrix.data(i, j, k) - Min) / (Max - Min) 'scales from 0-1
                    Temp = Temp * 21  'scales from 0-21
                    IndexH = CInt(Math.Ceiling(Temp))
                    IndexL = CInt(Math.Floor(Temp))
                    Temp = Temp - IndexL 'the decimal part

                    InterpolatedValue(0) = Base(IndexH, 0)
                    InterpolatedValue(1) = Base(IndexH, 1)
                    InterpolatedValue(2) = Base(IndexH, 2)

                    'InterpolatedValue(0) = 0.5 * (Temp * Base(IndexL, 0) + (1 - Temp) * Base(IndexH, 0)) * 255
                    'InterpolatedValue(1) = 0.5 * (Temp * Base(IndexL, 1) + (1 - Temp) * Base(IndexH, 1)) * 255
                    'InterpolatedValue(2) = 0.5 * (Temp * Base(IndexL, 2) + (1 - Temp) * Base(IndexH, 2)) * 255

                    ColorMatrix.data(i, j, k) = Color.FromArgb(CInt(InterpolatedValue(0)), CInt(InterpolatedValue(1)), CInt(InterpolatedValue(2)))
                Next
            Next
        Next

    End Sub
    Public Function ReturnColorMatrix(ByVal Values As MatrixDataStructures.Matrix3DSingle) As MatrixDataStructures.ColorMatrix

        Me.ValuesMatrix = Values
        ComputeColorMatrix()

        Return Me.ColorMatrix
    End Function

End Class